﻿using System;
using Transfer.DataLayer;
using Transfer.DataLayer.LAO;

namespace Transfer
{
    public delegate bool ValidateDoc(InputDocDS.DocHeaderRow dataRow);  // Внешний метод валидации документа

    /// <summary> Класс содержит реализации методов валидации входных данных.
    /// </summary>
    public class Validators
    {
        /// <summary> Класс логирования
        /// </summary>
        public ActivityLog ALog
        {
            get { return _aLog; }
            set { _aLog = value; }
        }
        private ActivityLog _aLog = new ActivityLog();  // Подключим логирование по умолчанию.

        public LaoDataSet laoDS; 

        public Validators()
        {
        }

        /// <summary> Метод проверяет корректность заголовка документа и корректность детальных строк.
        /// При обнаружении ошибки выводится сообщение в ActivityLog и возвращается признак ошибки.
        /// </summary>
        /// <param name="dataRow">Строка заголовка документа</param>
        /// <returns>true - ошибок нет, false - ошибка есть</returns>
        public bool DocValidate(InputDocDS.DocHeaderRow row)
        {
            bool doc_ok = true;

            #region ["Проверим значения полей в заголовке документа"]
            _aLog.Out_Log("Проверка документа № " + row.num_doc);

            if (row.num_doc.Trim() == String.Empty)
            {
                _aLog.Out_Log("    Номер документа не указан.");
                doc_ok = false;
            }

            if (row.type_doc.Trim() != "РсНак" && row.type_doc.Trim() != "ВзПкп")
            {
                _aLog.Out_Log("    Неизвестный тип документа - " + row.type_doc);
                doc_ok = false;
            }

            if (row.jrn_cd.Trim() == String.Empty)
            {
                _aLog.Out_Log("    Код журнала не указан.");
                doc_ok = false;
            }

            if (!CheckJournal(row.type_doc.Trim(), row.jrn_cd.Trim()))
            {
                _aLog.Out_Log("    Для входного типа документа {0} отсутствуют журналы с кодом {1}", row.type_doc, row.jrn_cd);
                doc_ok = false;
            }

            if (row.gpl_cd.Trim() == String.Empty)
            {
                _aLog.Out_Log("    Код грузополучателя не указан.");
                doc_ok = false;
            }

            if (laoDS.KAG.GetRcdByCode(row.gpl_cd) == 0)
            {
                _aLog.Out_Log("    Грузополучатель c кодом {0} не найден в ИС-ПРО.", row.gpl_cd);
                doc_ok = false;
            }

            #endregion ["Проверим значения полей в заголовке документа"]

            // Перебор и проверка детальных строк текущего документа
            foreach (InputDocDS.DocDetailRow rdet in row.GetChildRows("FK_DocHeader_DocDetail"))
            {
                if (!DetailValidate(rdet))
                    doc_ok = false;         // В детальной строке есть ошибка
            }
            return doc_ok;
        }

        /// <summary> Метод выполняет проверку одной детальной строки документа.
        /// </summary>
        /// <param name="row"></param>
        /// <returns></returns>
        private bool DetailValidate(InputDocDS.DocDetailRow row)
        {
            bool ok = true;

            if (row.nom_cd.Trim() == String.Empty)
            {
                _aLog.Out_Log("        Артикул номенклатуры не указан.");
                ok = false;
            }
            if (laoDS.Nom.GetRcdByCode(row.nom_cd) == 0)
            {
                _aLog.Out_Log("        Артикул номенклатуры {0} не найден в ИС-ПРО.", row.nom_cd);
                ok = false;
            }

            if (row.ei.Trim() == String.Empty)
            {
                _aLog.Out_Log("        Для артикула {0} не указана единица измерения.", row.nom_cd);
                ok = false;
            }
            if (laoDS.Nom.GetEiRcdByCode(row.ei) == 0)
            {
                _aLog.Out_Log("        Единица измерения {0} не найдена в ИС-ПРО.", row.ei);
                ok = false;
            }

            return ok;
        }

        /// <summary> Метод реализует специфическую проверку на наличие в ИС-ПРО связанных журналов
        /// в зависимости от типа входного документа.
        /// </summary>
        /// <param name="docType"></param>
        /// <param name="jrn_code"></param>
        /// <returns></returns>
        private bool CheckJournal(string docType, string jrn_code)
        {
            bool ok = true;
            // По указанному типу документа определяем - какие журналы должны быть, и проверяем их наличие в ИС-ПРО.
            if (docType == "РсНак" && (laoDS.Jrn.GetRcdByCode(jrn_code, CdDoc.IncomBill) == 0 || laoDS.Jrn.GetRcdByCode(jrn_code, CdDoc.OutcomBill) == 0))
                ok = false;
            if (docType == "ВзПкп" && (laoDS.Jrn.GetRcdByCode(jrn_code, CdDoc.ReversIncomBill) == 0 || laoDS.Jrn.GetRcdByCode(jrn_code, CdDoc.ReversOutcomBill) == 0))
                ok = false;
            return ok;
        }
    }
}
